package org.example.leetCode;


import java.util.List;

/**
 * 120. 三角形最小路径和
 * 给定一个三角形 triangle ，找出自顶向下的最小路径和。
 * 每一步只能移动到下一行中相邻的结点上。
 * 相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。
 * 也就是说，如果正位于当前行的下标 i ，那么下一步可以移动到下一行的下标 i 或 i + 1 。
 */
public class Code120 {
    /**
     * 自上向下动态规划
     * @param triangle 三角形数组
     * @return 最小路径和
     */
    public static int minimumTotal(List<List<Integer>> triangle) {
        if (triangle == null || triangle.isEmpty()) {
            return 0;
        }
        int[] dp = new int[triangle.size()];
        dp[0]=triangle.get(0).get(0);
        List<Integer> triangleRow;
        for (int row = 1; row < triangle.size(); row++) {
            triangleRow = triangle.get(row);
            for(int list=row;list>=0;list--){
                if(list==0) {
                    //最左边
                    dp[list] =dp[list]+triangleRow.get(list);
                }else if(list==row){
                    //最右边
                    dp[list] =dp[list-1]+triangleRow.get(list);
                }else{
                    //中间
                    dp[list] = Math.min(dp[list], dp[list - 1])+triangleRow.get(list);
                }
            }
        }

        int result = dp[0];
        for (int i = 1; i < triangle.size(); i++) {
            result = Math.min(result, dp[i]); // 找到最后一行的最小值
        }
        return result;
    }

    /**
     * 自底向上动态规划
     * @param triangle 三角形数组
     * @return 最小路径和
     */
    public static int minimumTotal1(List<List<Integer>> triangle) {
        int n = triangle.size();
        int[] dp = new int[n];

        // 初始化为最后一行
        for (int i = 0; i < n; i++) {
            dp[i] = triangle.get(n - 1).get(i);
        }

        // 自底向上动态规划
        for (int row = n - 2; row >= 0; row--) {
            for (int col = 0; col <= row; col++) {
                dp[col] = Math.min(dp[col], dp[col + 1]) + triangle.get(row).get(col);
            }
        }

        return dp[0];
    }
}
